﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

// brief: HTTP下载相关的类
#pragma once

#include "GmepComponentUtils.h"
#include "GbmpDefines.h"
#include <chrono>

namespace web
{
    namespace json
    {
        class value;
    }
    class  uri_builder;
    namespace http
    {
        class http_request;
        namespace client
        {
            class http_client;
        }
    }
}
namespace Json
{
    class Value;
}
namespace gmep
{
    class IGmepCategoryInfo;
}

class QJsonArray;
class QJsonObject;
struct GmepComponentPlaceHolderInfo;
struct GmepComponentType;

class GMEP_COMPONENT_UTILS_EXPORT ComponentCommonUtils
{
public:
    //static void AddRequestHeader(std::shared_ptr<web::http::http_request>& req, const std::wstring& strAccountId, const std::wstring& strTokenId, bool setContentType);
    static void AddRequestHeader(web::http::http_request & req, const std::wstring& strAccountId, const std::wstring& strTokenId, bool setContentType);
    static void GetPublicAccoutAndToken(std::wstring& strAccountId, std::wstring& strTokenId);

    /// \brief 发送http请求
    /// \param hostUrl - hostUrl，由于构造client
    /// \param deviceId - 设备id
    /// \param spid - 用户spid
    /// \param response - 接口返回数据
    /// \param bNeedContentType - 是否需要添加Content-Type为application/json 默认添加
    /// \param strRequestMethod - 请求方法 GET POST PUT
    /// \param body_data - 请求主体数据
    /// \param retryCount - 失败后重试次数
    /// \return 请求成功返回true
    static bool SendHttpRequst_Aecore(
        const std::wstring & hostUrl,
        const std::wstring & deviceId,
        const std::wstring & spid,
        std::string & response,
        const bool & bNeedContentType = true,
        const std::string& body_data = "",
        const int & retryCount = 5);

    /// \brief 发送http请求
    /// \param hostUrl - hostUrl，由于构造client
    /// \param strAccountId - 用户id
    /// \param strTokenId - 用户token
    /// \param requestUri - 请求接口地址
    /// \param response - 接口返回数据
    /// \param bNeedContentType - 是否需要添加Content-Type为application/json 默认添加
    /// \param strRequestMethod - 请求方法 GET POST PUT
    /// \param body_data - 请求主体数据
    /// \param retryCount - 失败后重试次数
    /// \return 请求成功返回true
    static bool SendHttpRequst(
        const std::wstring & hostUrl,
        const std::wstring &strAccountId,
        const std::wstring &strTokenId,
        const web::uri_builder &requestUri,
        std::string& response,
        const bool & bNeedContentType = true,
        const std::wstring & strRequestMethod = L"GET",
        const std::string& body_data = "",
        const int & retryCount = 5);

    static bool SendHttpRequstMain(
        const std::wstring & hostUrl,
        const std::wstring &strAccountId,
        const std::wstring &strTokenId,
        const web::uri_builder &requestUri,
        std::string& response,
        const bool & bNeedContentType = true,
        const std::wstring& strRequestMethod = L"GET",
        const std::string& body_data = "",
        const int & retryCount = 5);

    ///-----Todo:下面为重载上面的接口，用于特殊处理小写json库的数据接口使用，后续需讨论解决，统一接口
    static bool SendHttpRequst(
        const std::wstring & hostUrl,
        const std::wstring &strAccountId,
        const std::wstring &strTokenId,
        const web::uri_builder &requestUri,
        web::json::value & resultValue,
        const bool & bNeedContentType = true,
        const std::wstring & strRequestMethod = L"GET",
        const std::string& body_data = "",
        const int & retryCount = 5);

    static bool SendHttpRequstMain(
        const std::wstring & hostUrl,
        const std::wstring &strAccountId,
        const std::wstring &strTokenId,
        const web::uri_builder &requestUri,
        web::json::value & resultValue,
        const bool & bNeedContentType = true,
        const std::wstring& strRequestMethod = L"GET",
        const std::string& body_data = "",
        const int & retryCount = 5);
    
    static int ExceptFilterFunc(EXCEPTION_POINTERS *pExp);

    static bool GetComponentFamilyTypeDetail(const gmep::IGmepCategoryInfo* pCateInfo, Json::Value typeData, Json::Value parametersValue, GmepComponentType& retCompType);

    static bool GetProjectComponent2DPlaceHolderInfo(const Json::Value placeholderValue,
        GmepComponentPlaceHolderInfo& planPlaceHolderInfo,
        GmepComponentPlaceHolderInfo& elevationPlaceHolderInfo,
        GmepComponentPlaceHolderInfo& profilePlaceHolderInfo,
        GmepComponentPlaceHolderInfo& electricPlaceHolderInfo,
        std::wstring& strMainPlaceHolderId,
        bool isPrivateEnv = false);

    static void QueryExist2DPlaceHoldersFromDb3(const std::wstring& dbFilePath, const std::vector<std::wstring>& publicPlaceHolderIdVec,
        std::map<std::wstring, GmepComponentPlaceHolderInfo>& retSharePlaceHolderInfo,
        std::map<std::wstring, GmepComponentPlaceHolderInfo>& retProjectPlaceHolderInfo,
        std::map<std::wstring, GmepComponentPlaceHolderInfo>& retPublicPlaceHolderInfo,
        std::map<std::wstring, GmepComponentPlaceHolderInfo>& retEnterprisePlaceHolderInfo);

    static bool write_to_file(const std::wstring& file_path, const std::string& data);
    static bool DownloadFile(const std::wstring& strURL, const std::wstring& fullFilePath);

    static std::wstring GetGdcAPIHost(const std::wstring configType = L"structure");
    static std::wstring GetGjwAPIHost();
    static std::wstring GetGjwAPIEndPointHost();

    // 获取 某分类下的业务属性的定义
    static QJsonArray GetCategoryProperty(const std::wstring& sCategoryCode);
    static std::map<std::wstring, std::tuple<std::wstring, std::wstring>> GetCategoryPropertyMap(const std::wstring& sCategoryCode);

    // 获取参数定义中几何参数的定义，返回字符串，用于存到db3
    static std::wstring GetGeometryParamDefinitionString(const Json::Value& paramDef);
    // 由 字符串 获取QJason
    static QJsonArray GetGeometryParamDefinition(const std::wstring& paramDefStr);
    // 由 字符串 获取 所有几何参数<name,definition>的 map
    static std::map<std::wstring, QJsonObject> ParseComponentGeometryDefinition(const std::wstring& strGeomDef);

    static bool IsValueEditable(bool isGeometry, bool isDrivingParameter, bool isOutputParameter);

    static std::wstring GetTokenInQa();

	//static bool GetCategoryComponents(const std::wstring & projectId, const std::vector<std::wstring>& categoryCodes, std::map<std::wstring,HttpComponentInfo> & mapComponentInfo);
    // 获取公共库图例下载地址
    static bool GetPublicPlaceholderDownloadUrl(const std::wstring softCode, const std::wstring componentId, const std::wstring softVersion,std::string& result);
    // 获取公共库图例的信息
    static bool GetPublicPlaceHolderInfoFromJson(const Json::Value& Val, const std::wstring& cateoryCode,
        const std::wstring& str2DCategoryFolder, GmepComponentPlaceHolderInfo& placeHolderInfo);
    ////获取项目库构件对应图例下载地址
    //static bool GetProjectPlaceholderDownloadUrl( const std::wstring& clientString, const std::wstring& projectId, const std::wstring& componentId, const std::wstring& version,
    //    const std::wstring& placeholderId,std::string& result);
    
    // 获取企业库中图例的下载地址
    static bool GetEnterprisePlaceholderDownloadUrl(const std::wstring& enterpriseId,const std::wstring& componentId, std::string& result);

    static bool GetLibraryPlaceholderGacDownloadUrl(const std::wstring& spaceInfo,const std::wstring& gacUrl, std::string& result);
    
    // 获取企业库ID
    static bool GetEnterpriseId(std::wstring& enterpriseId);

    //读取企业库搜索spu
    static bool GetEnterpriseSearchSPU(
        const std::wstring & categoryGuid,
        const std::wstring & enterpriseId,
        const std::wstring  & major,
        const std::wstring& type,
        const int32_t & pageSize,
        std::string &result);

    /// \brief 解析企业图例库spu信息
    ///  
    /// \param jsonResult 请求得到的json
    /// \param legendData 解析后的信息 id, name, major, type, resource_id, resource_version, url, category_id
    /// \param totalCount 获取到的图例数量
    /// \return bool
    static bool ReadEnterprisePlaceholderInfo(const std::string& jsonResult,
        std::vector<std::tuple<std::wstring, std::wstring, std::wstring, std::wstring, std::wstring, int, std::wstring, std::wstring>>& legendData, int & totalCount);

    static bool GetLibraryPlaceholderId(const std::wstring & resourceId, const std::wstring& spaceInfo, std::wstring& placeholderId, std::wstring& gacUrl);

    /// \brief 绑定企业库图例
    /// 
    /// \param projectId 协同项目ID
    /// \param body 构件企业图例相关信息
    /// \param result 返回请求结果
    /// \return bool
    static bool BindingEnterprisePlaceholder(const std::wstring& projectId, const std::string& body, std::string & result);

    static std::wstring UpdatePlaceholderName(const std::wstring& name, const std::wstring& placeholderName, const int& placeholderFrom);

    static double GetUsedTime(const std::wstring & title, const std::chrono::time_point<std::chrono::steady_clock>& startTimePoint);

    /// \brief 获取图例的空间信息
    /// \param spaceTypeParameter 存在空间的id，目前只需要传入企业库id
    /// \param placeholderFrom 图例来源，1企业库 2机电共相空间
    /// \return 
    static std::wstring GetLibrarySpaceInfo(const std::wstring& spaceTypeParameter, int placeholderFrom);

    static void SetNeedFYI(bool needFyi);

    /// \ 根据datasetId获取工作单元的软件版本，用于与当前软件版本进行比较
    static bool GetAppVersion(const std::wstring& datasetId, std::string& modelingAppVersion);
};
